﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Net;

namespace Argos.Net
{
	/// <summary>
	/// Provides network credentials that can be serialized.
	/// </summary>
	[Serializable]
	[DefaultProperty("UserName")]
	public sealed class Credential : ICredentials
	{

		#region #ctor: public Credential()

		/// <summary>
		/// Creates a new instance of the class.
		/// </summary>
		public Credential() { }

		#endregion

		#region #ctor: public Credential(string userName, string password)

		/// <summary>
		/// Creates a new instance of the class and specifies the user name
		/// and password for the new instnace.
		/// </summary>
		public Credential(string userName, string password) : this(userName, password, null) { }

		#endregion

		#region #ctor: public Credential(string userName, string password, string domain)

		/// <summary>
		/// Creates a new instance of the class and specifies the user name,
		/// password and domain for the new instance.
		/// </summary>
		public Credential(string userName, string password, string domain)
		{
			this.UserName = userName;
			this.Password = password;
			this.Domain = domain;
		}

		#endregion



		#region public string UserName { get; set; }

		/// <summary>
		/// Gets or sets the user name associated with the credentials.
		/// </summary>
		[Category("Credentials")]
		[DisplayName("User Name")]
		[Description("Specifies the user name associated with the credentials.")]
		public string UserName { get; set; }

		#endregion

		#region public string Password { get; set; }

		/// <summary>
		/// Gets or sets the password for the user name associated with the credentials.
		/// </summary>
		[Category("Credentials")]
		[Description("Specifies the password for the user name associated with the credentials.")]
		[PasswordPropertyText(true)]
		public string Password { get; set; }

		#endregion

		#region public string Domain { get; set; }

		/// <summary>
		/// Gets or sets the domain or computer name that verifies the credentials.
		/// </summary>
		[Category("Credentials")]
		[Description("Specifies the domain or computer name that verifies the credentials.")]
		public string Domain { get; set; }

		#endregion



		#region public override bool Equals(object obj)

		/// <summary>
		/// Compares the given object to the current.
		/// </summary>
		/// <param name="obj">The object to compare to the current.</param>
		public override bool Equals(object obj)
		{
			if (obj is Credential)
			{
				Credential c = (Credential)obj;
				return string.Equals(this.UserName, c.UserName) && string.Equals(this.Password, c.Password) && string.Equals(this.Domain, c.Domain);
			}

			return false;
		}

		#endregion

		#region public NetworkCredential GetCredential(Uri uri, string authType)

		/// <summary>
		/// Returns a <see cref="NetworkCredential"/> instance with the specified
		/// <see cref="UserName"/>, <see cref="Password"/> and <see cref="Domain"/> properties.
		/// </summary>
		public NetworkCredential GetCredential(Uri uri, string authType)
		{
			if (!string.IsNullOrEmpty(this.Domain))
			{
				return new NetworkCredential(this.UserName, this.Password, this.Domain);
			}
			return new NetworkCredential(this.UserName, this.Password);
		}

		#endregion
		
		#region public override int GetHashCode()

		/// <summary>
		/// Returns the has code for the current instance.
		/// </summary>
		/// <returns></returns>
		public override int GetHashCode()
		{
			ArrayList list = new ArrayList();
			list.Add(this.UserName);
			list.Add(this.Password);
			list.Add(this.Domain);

			return list.ToArray().GetHashCode();
		}

		#endregion

		#region public override string ToString()

		/// <summary>
		/// Returns the string representation of the credentials.
		/// </summary>
		public override string ToString()
		{
			if (!string.IsNullOrEmpty(this.UserName))
			{
				if (!string.IsNullOrEmpty(this.Domain))
				{
					return string.Format(@"{0}\{1}", this.Domain, this.UserName);
				}
				else
				{
					return this.UserName;
				}
			}

			return "(None)";
		}

		#endregion

	}
}
